package main

import (
	"fmt"
	"github.com/gogf/gf/container/gtype"
	"github.com/gogf/gf/os/gcmd"
	"github.com/gogf/gf/os/gfile"
	"github.com/gogf/gf/text/gregex"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
)

func Help() {
	fmt.Print(gstr.TrimLeft(`
USAGE 
    md FILE [OPTION]

ARGUMENT
    FILE  add.

OPTION
    add      	add toc number
    rm,remove   remove toc number
    re,reload   reload toc number

EXAMPLES
    md filepath
    md filepath rm
    md filepath re

`))
}

// 开始标识符
var mdStart = [maxLevel]string{"#####", "####", "###", "##", "#"}

// 最大级别
const maxLevel int = 5
const CRCN string = "\r\n"
const CN string = "\n"

// 目录
type TOC struct {
	levels []gtype.Int
}

func NewTOC() *TOC {
	data := make([]gtype.Int, maxLevel)
	return &TOC{levels: data}
}

// level级别数量加一
func (t *TOC) add(level int) {
	for i := maxLevel - 1; i > (level - 1); i-- {
		t.levels[i].Set(0)
	}
	t.levels[(level - 1)].Add(1)
}

// 返回级别展示
func (t TOC) get(level int) string {
	tmpSilce := t.levels[0:level]
	strSile := make([]string, len(tmpSilce))
	for i, tmp := range tmpSilce {
		strSile[i] = gconv.String(tmp.Val())
	}
	return gstr.Join(strSile, ".")
}

func main() {
	// cmd传递文件
	file := gcmd.GetArg(1)
	if file == "" {
		fmt.Println("please input file path!")
		Help()
		return
	}

	if file == "h" || file == "help" {
		Help()
		return
	}

	handle := gcmd.GetArg(2)

	if handle == "rm" || handle == "remove" {
		removeToc(file)
	} else if handle == "re" || handle == "reload" {
		// 重新加载
		removeToc(file)
		addToc(file)
	} else {
		addToc(file)
	}

}

func addToc(file string) {
	fmt.Println("addToc start...")
	fmt.Println(file)

	toc := NewTOC()
	// 备份临时文件
	err := gfile.Copy(file, file+".tmp")
	if err != nil {
		panic(err)
	}

	content := gfile.GetContents(file)
	writeStr := ""
	endSymbol := CRCN
	if !gstr.Contains(content, endSymbol) {
		endSymbol = CN
	}

	contentLines := gstr.Split(content, endSymbol)
	for index, line := range contentLines {
		flag := true
		for i, start := range mdStart {
			if gstr.HasPrefix(line, start) {
				level := 5 - i
				if level == 1 && gstr.HasPrefix(line[level+1:], "1") {
					// 删除临时备份文件
					err := gfile.Remove(file + ".tmp")
					if err != nil {
						panic(err)
					}
					fmt.Println("The file has been marked!")
					return
				}

				toc.add(level)
				writeStr += start + " " + toc.get(level) + " " + line[level+1:]
				flag = false
				break
			}
		}
		if flag {
			writeStr += line
		}

		if index != len(contentLines)-1 {
			writeStr += endSymbol
		}
	}
	gfile.PutContents(file, writeStr)

	// 备份
	err = gfile.Move(file+".tmp", file+".bak")
	if err != nil {
		panic(err)
	}

	fmt.Println("addToc end~!~")
}

func removeToc(file string) {
	fmt.Println("removeToc start...")
	fmt.Println(file)

	// 备份临时文件
	err := gfile.Copy(file, file+".tmp")
	if err != nil {
		panic(err)
	}

	content := gfile.GetContents(file)
	writeStr := ""
	endSymbol := CRCN
	if !gstr.Contains(content, endSymbol) {
		endSymbol = CN
	}
	contentLines := gstr.Split(content, endSymbol)
	for index, line := range contentLines {
		flag := true
		for i, start := range mdStart {
			if gstr.HasPrefix(line, start) {
				level := 5 - i
				tmpStr := line[level:]
				replaceStr, err := gregex.ReplaceString(`\s\d(.\d{1,3}){0,4}\s`, " ", tmpStr)
				if err != nil {
					panic(err)
				}

				if replaceStr != tmpStr {
					writeStr += start + replaceStr
					flag = false
					break
				}

			}
		}
		if flag {
			writeStr += line
		}

		if index != len(contentLines)-1 {
			writeStr += endSymbol
		}
	}
	gfile.PutContents(file, writeStr)

	// 备份
	err = gfile.Move(file+".tmp", file+".bak")
	if err != nil {
		panic(err)
	}

	fmt.Println("removeToc end~!~")
}
